#ifndef NSI_SPIKE_UTIL_BACKTRACE_H
#define NSI_SPIKE_UTIL_BACKTRACE_H

#include <stdio.h>

namespace nsi {
namespace spike {

class backtrace
{
public:

  // Backtrace types
  typedef void* address_type;
  typedef char* symbol_type;

  enum default_types
  {
    default_depth = 20
  };

  // Default constructor
  explicit backtrace();

  // Constructor given a max depth
  explicit backtrace(int max_depth);

  // Destructor
  ~backtrace();

  // Creates the backtrace
  bool create();

  bool create(const address_type signal);

  // Destroys the current backtrace
  void destroy();

  // Print out the backtrace
  void print() const;

  void print(FILE* file) const;

  // Accessors
  // If the backtrace has been created
  bool created() const
  {
    return addresses_ != 0 && symbols_ != 0;
  }

  // Depth of the backtrace
  int depth() const
  {
    return depth_;
  }

  // Max depth of the backtrace
  int max_depth() const
  {
    return max_depth_;
  }

  // List of addresses
  address_type* addresses() const
  {
    return addresses_;
  }

  // List of symbols
  symbol_type* symbols() const
  {
    return symbols_;
  }

  // Fetch an address
  address_type address(int index) const
  {
    return addresses_[index];
  }

  // Fetch a symbol
  symbol_type symbol(int index) const
  {
    return symbols_[index];
  }

protected:

  // Create the list of addresses
  bool create_addresses();
  // Create the list of symbols
  bool create_symbols();

  // Delete the list of addresses
  void destroy_addresses();
  // Delete the list of symbols
  void destroy_symbols();

private:
  // No copy constructor
  backtrace(const backtrace&);
  // No assignment operator
  backtrace& operator=(const backtrace&);

  // Depth of the backtrace
  int depth_;
  // Max depth of the backtrace
  int max_depth_;
  // List of addresses
  address_type* addresses_;
  // List of symbols
  symbol_type* symbols_;
};

} // namespace spike
} // namespace nsi

#endif // !NSI_SPIKE_UTIL_BACKTRACE_H
